#pragma once

#include "Comm.hpp"
#define SIZE 128
#define NUM 64

// 提前声明
class Event;
class Reactor;

// 类型重命名
typedef int (*callback_t)(Event *ev);

// 需要让epoll管理的基本节点
class Event
{
public:
    // 文件描述符
    int _sock;
    // _sock对应的输入缓冲区
    std::string _inbuffer;
    // _sock对应的输出缓冲区
    std::string _outbuffer;

    // 回调
    callback_t _recver;
    callback_t _sender;
    callback_t _errorer;

    // Event回指Reactor
    Reactor *_R;

    Event()
        : _sock(-1), _recver(nullptr), _sender(nullptr), _errorer(nullptr), _R(nullptr)
    {
    }

    // 设置成员变量中的回调
    void RegisterCallback(callback_t recver, callback_t sender, callback_t errorer)
    {
        _recver = recver;
        _sender = sender;
        _errorer = errorer;
    }

    ~Event() {}
};

// 不需要关心任何sock的类型,只关心如何使用Reactor管理Event
// Reactor : Event = 1 : n
class Reactor
{
public:
    Reactor()
        : _epfd(-1)
    {
    }

    void InitReactor()
    {
        // 创建epoll模型
        _epfd = epoll_create(SIZE);
        if (_epfd < 0)
        {
            std::cerr << "epoll create failed" << std::endl;
            exit(2);
        }
        std::cout << "InitReactor success, _epfd: " << _epfd << std::endl;
    }

    // 增加
    bool InsertEvent(Event *pev, uint32_t evs)
    {
        // 1. 将pev->_sock和evs事件插入到_epfd模型中
        struct epoll_event ev;
        ev.events = evs;
        ev.data.fd = pev->_sock;
        if (epoll_ctl(_epfd, EPOLL_CTL_ADD, pev->_sock, &ev) < 0)
        {
            std::cerr << "epoll add event error" << std::endl;
            return false;
        }
        // 2. ev本身插入到_events中
        _events[pev->_sock] = pev;

        return true;
    }

    // 删除
    bool DeleteEvent(Event *pev)
    {
        // 1. 将pev->_sock从_epfd模型中删除
        if (epoll_ctl(_epfd, EPOLL_CTL_DEL, pev->_sock, nullptr) < 0)
        {
            std::cerr << "epoll add event error" << std::endl;
            return false;
        }
        // 2. 遍历迭代器,查找_events中的pev->_sock,将其删除
        std::unordered_map<int, Event *>::iterator it = _events.find(pev->_sock);
        if (it != _events.end())
        {
            _events.erase(it);
        }
        // 3. close
        close(pev->_sock);
        // 4. delete
        delete pev;
        return true;
    }

    // 修改
    bool EnableRW(int sock, bool enableread, bool enablewrite)
    {
        struct epoll_event ev;
        ev.events = EPOLLET | (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT : 0);
        ev.data.fd = sock;
        if (epoll_ctl(_epfd, EPOLL_CTL_MOD, sock, &ev))
        {
            std::cerr << "epoll mod event error" << std::endl;
            return false;
        }
        return true;
    }

    // 就绪事件派发器
    void Dispatcher(int timeout)
    {
        // 通过epoll_wait获取就绪事件
        struct epoll_event revs[NUM];
        // timeout以内是阻塞等待,timeout之后是非阻塞
        // 若没有接收到就绪事件,直接返回且n为0,不进入for循环
        int n = epoll_wait(_epfd, revs, NUM, timeout);
        for (int i = 0; i < n; ++i)
        {
            int sock = revs[i].data.fd;
            uint32_t revents = revs[i].events;
            // 错误处理 ———— 对端链接发生错误
            if (revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            // 错误处理 ———— 对端链接挂断
            if (revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);

            // 当检测到读就绪时, 调用Event中的_recver回调函数
            if (revents & EPOLLIN)
                _events[sock]->_recver(_events[sock]);

            // 当检测到写就绪时, 调用Event中的_sender回调函数
            if (revents & EPOLLOUT)
                _events[sock]->_sender(_events[sock]);
        }
    }

    ~Reactor()
    {
    }

private:
    // epoll模型
    int _epfd;
    // 文件描述符和Event节点对应关系 ———— 管理的所有的Event节点的集合
    std::unordered_map<int, Event *> _events;
};